home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
c
/
cpptask1.zip
/
TASK.H
< prev
next >
Wrap
C/C++ Source or Header
|
1991-02-07
|
5KB
|
189 lines
/**********************************************************************
*
* NAME: task.h
*
* DESCRIPTION: modified version of Bruce Eckel's C++ task manager
* from Computer Language Feb. 1991
*
* note that the variable naming conventions are somewhat
* "Hungarian" in nature, but not so as to be unreadable
*
* M O D I F I C A T I O N H I S T O R Y
*
* when who what
* -------------------------------------------------------------------
* 02/04/91 J. Alan Eldridge created
*
* 02/05/91 JAE modified so it would run: made each
* task have its own stack to eliminate
* the stack copying (which is not only
* ugly and limiting, but dangerous as well)
*
* added semaphores for task waiting
*
* 02/07/91 JAE changed from arrays of tasks, semas to
* singly linked list
*
*********************************************************************/
#ifndef __TASK_H
#define __TASK_H 1
#ifndef __AEDEF_H
#include "aedef.h"
#endif
// fatal error handler (this never returns)
extern void tskFatal(char *fmt, ...);
// this is the base class, since we need lists of both
// Tasks and Semas, but want only one type of list
class TskObj {
private:
TskObj *link; // link to next object in list
public:
TskObj(): link(0)
{ }
virtual ~TskObj()
{ }
TskObj *next() // return ptr to next object
{ return link; }
void linkTo(TskObj *o) // set ptr to next object
{ link = o; }
};
class TskList {
private:
int cObj; // count of objects
TskObj *pHead, // ptr to first on list
*pTail; // ptr to last on list
public:
TskList(): cObj(0), pHead(0), pTail(0)
{ }
int count()
{ return cObj; }
void append(TskObj *o);
TskObj *first()
{ return pHead; }
};
class Sema; // establish the name
class Task; // establish the name
class Scheduler {
private:
TskList semas; // list of semas
TskList tasks; // list of tasks
Task *pTask; // the current task
jmp_buf schEnv; // environment in scheduler
void runATask(); // try to run one task: return
// if we are deadlocked
Sema *findSema(uchar *sname); // look up sema in semas
public:
Scheduler(): pTask(0)
{ }
void endProcess()
{ longjmp(schEnv, -1); }
void giveUpTask()
{ longjmp(schEnv, 1); }
void addTask(Task *t); // inline, but later
void run();
void addSema(Sema *s); // inline, but later
void signalSema(uchar *sname, Task *t, int units = 1);
void waitSema(uchar *sname, Task *t);
};
class Sema: public TskObj {
private:
uchar *sName; // name of semaphore
int value; // > 0 means task can wake up
Task *tskWaiting; // what task is waiting on it
public:
Sema(uchar *semaName): sName(semaName), value(0), tskWaiting(0)
{ }
~Sema()
{ }
uchar *name()
{ return sName; }
void signal(Task *t, int units = 1);
void wait(Task *t);
};
class Task: public TskObj {
private:
uint ready: 1; // can task run?
uchar *tName; // name of task
const int stkLen; // stack size
jmp_buf tskEnv; // for context switching
Scheduler &owner; // who controls this task
uchar far *stack; // local stack for task
public:
Task(uchar *name, Scheduler &s, int len = 0x1000);
virtual ~Task();
int isReady()
{ return ready; }
void makeReady()
{ ready = 1; }
void makeWait()
{ ready = 0; }
uchar *name()
{ return tName; }
int isInited()
{ return stack != 0; }
void init(); // never returns
virtual void tskMain() = 0; // must derive a class to use this
void suspend(); // give up to scheduler
void resume(); // wake up and continue right after
// last call to suspend()
void endProcess() // make the scheduler return
{ owner.endProcess(); }
void addSema(Sema *s)
{ owner.addSema(s); }
void signalSema(uchar *semaName, int units = 1)
{ owner.signalSema(semaName, this, units); }
void waitSema(uchar *semaName)
{ owner.waitSema(semaName, this); }
};
inline void Scheduler::addSema(Sema *s)
{ semas.append(s); }
inline void Scheduler::addTask(Task *t)
{ tasks.append(t); }
#endif